package com.abocode.aichat.server.context.endpoint;

import com.abocode.aichat.server.context.ServerRuntimeContext;
import com.abocode.aichat.server.modules.Module;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.List;

/**
 * @author guanxf
 */
@Getter
@Setter
public abstract class ServerEndpoint implements Endpoint {
    protected static Log log = LogFactory.getLog(ServerEndpoint.class);
    private String name;
    private int parentSize;
    private int childSize;
    private int port;
    private String domain;
    private ServerRuntimeContext serverRuntimeContext;
    private List<Module> moduleRegistries;
    private EventLoopGroup parent = new NioEventLoopGroup(parentSize);
    private EventLoopGroup child = new NioEventLoopGroup(childSize);
    private ChannelFuture channelFuture = null;
    public ServerRuntimeContext getServerRuntimeContext() {
        return serverRuntimeContext;
    }
    public void setServerRuntimeContext(ServerRuntimeContext serverRuntimeContext) {
        this.serverRuntimeContext = serverRuntimeContext;
    }

    @Override
    public String getName() {
        return name;
    }


    @Override
    public String getDomain() {
        return domain;
    }

    @Override
    public void shutdown() {
        try {
            child.shutdownGracefully();
            parent.shutdownGracefully();
            channelFuture.channel().close().sync();
        } catch (InterruptedException e) {
            if (log.isDebugEnabled()) {
                log.debug("shutdown error", e);
            }
        }
    }

    protected void init() {
        if (serverRuntimeContext == null) {
            throw new NullPointerException("serverRuntimeContext is null");
        }
        serverRuntimeContext.setDomain(getDomain());
        serverRuntimeContext.setName(getName());
        for (Module moduleRegistry : moduleRegistries) {
            serverRuntimeContext.getWorker().addModule(moduleRegistry);
        }
    }

    @Override
    public void start() {
        init();
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(parent, child);
        bootstrap.childOption(ChannelOption.CONNECT_TIMEOUT_MILLIS,10);
        bootstrap.childOption(ChannelOption.TCP_NODELAY,true);
        bootstrap.channel(NioServerSocketChannel.class);
        bootstrap.childHandler(channelHandler());
        try {
            channelFuture = bootstrap.bind(port).sync();
        } catch (InterruptedException e) {
            if (log.isDebugEnabled()) {
                log.debug("start error", e);
            }
        }
    }
}
